import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @author wcj
 * @Date 2021/6/17 14:37
 * @Version 1.0
 */
public class CountTask extends RecursiveTask<Integer> {

    private static final int THRESHOLD = 2;

    private int start;
    private int end;

    public CountTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    /**
     * Fork-Join框架：利用分治思想，将大任务拆分为小任务，执行完成之后再对结果进行合并得到最终的结果
     * 其利用了工作窃取模式，即每个线程都有自己对应的双端工作队列，但是有的线程很快执行完成之后，可以从其它线程的工作队列队尾窃取任务
     * 优点：充分利用多线程资源，加快计算
     * 缺点：当队列中只有一个任务时存在线程对于资源的竞争，并且需要用到多个线程和多个双端队列
     * ForkJoinPool去提交ForkJoinTask(RecursiveAction无返回结果，RecursiveTask有返回结果)
     *
     * @return
     */
    @Override
    protected Integer compute() {
        int sum = 0;

        boolean compute = (end - start) <= THRESHOLD;
        if (compute) {
            for (int i = start; i <= end; i++) {
                sum += i;
            }
        } else {
            int mid = (start + end) / 2;
            CountTask leftTask = new CountTask(start, mid);
            CountTask rightTask = new CountTask(mid + 1, end);
            leftTask.fork();
            rightTask.fork();
            int leftTaskRes = leftTask.join();
            int rightTaskRes = rightTask.join();
            sum = leftTaskRes + rightTaskRes;
        }
        return sum;
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        CountTask countTask = new CountTask(1, 4);
        ForkJoinTask<Integer> submit = forkJoinPool.submit(countTask);
        try {
            System.out.println(submit.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
